import { my_message } from "@/utils/my_message/index.js";

const msg = my_message();

/**
 * 将指定文件中的图片绘制到 canvas 上，并根据最大尺寸进行缩放和居中处理
 * @param {File} file - 包含图片的文件对象
 * @param {CanvasRenderingContext2D} ctx - canvas 的 2D 渲染上下文
 * @param {number} maxSize - 图片绘制的最大宽度和高度
 */
const draw_image_to_canvas = (file, ctx, maxSize) => {
  const img = new Image();
  const url = URL.createObjectURL(file);
  img.onload = function () {
    // 确定图片的缩放尺寸
    let drawWidth = img.width;
    let drawHeight = img.height;
    if (drawWidth > maxSize || drawHeight > maxSize) {
      // 图片过大，等比例缩小
      const widthRatio = maxSize / drawWidth;
      const heightRatio = maxSize / drawHeight;
      const ratio = Math.min(widthRatio, heightRatio);
      drawWidth = Math.floor(drawWidth * ratio);
      drawHeight = Math.floor(drawHeight * ratio);
    } else {
      // 图片过小，等比例放大
      const widthRatio = maxSize / drawWidth;
      const heightRatio = maxSize / drawHeight;
      const ratio = Math.max(widthRatio, heightRatio);
      drawWidth = Math.floor(drawWidth * ratio);
      drawHeight = Math.floor(drawHeight * ratio);

      // 确保不会超过 500x500（虽然理论上不会，因为已经按比例计算）
      drawWidth = Math.min(drawWidth, maxSize);
      drawHeight = Math.min(drawHeight, maxSize);
    }

    // 计算绘制起始位置以保持图片居中
    const startX = (maxSize - drawWidth) / 2;
    const startY = (maxSize - drawHeight) / 2;

    // 将图片绘制到 canvas 上
    ctx.clearRect(0, 0, maxSize, maxSize); // 清除画布
    ctx.drawImage(img, startX, startY, drawWidth, drawHeight);
    // 释放对象 URL
    URL.revokeObjectURL(url);
  };
  img.src = url;
};

/**
 * 获取 canvas 上指定坐标位置的像素颜色信息
 * @param {number} [x=0] - 要获取颜色的像素点的 x 坐标，默认为 0
 * @param {number} [y=0] - 要获取颜色的像素点的 y 坐标，默认为 0
 * @param {CanvasRenderingContext2D} ctx - canvas 的 2D 渲染上下文
 * @returns {Object} - 包含该像素点颜色信息的对象，包含 r（红）、g（绿）、b（蓝）、a（透明度）、rgba_str（RGBA 字符串）和 hex_str（十六进制颜色字符串）属性
 */
const get_color = (x = 0, y = 0, ctx) => {
  const imageData = ctx.getImageData(x, y, 1, 1);
  const data = imageData.data;
  const r = data[0];
  const g = data[1];
  const b = data[2];
  const a = data[3]; // Alpha 通道
  return {
    r,
    g,
    b,
    a,
    rgba_str: `rgba(${r}, ${g}, ${b}, ${a / 255})`,
    hex_str: `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, "0")}`,
  };
};

/**
 * 将 RGB 颜色转换为 HSL 颜色，根据亮度调整值调整亮度，再转换回 RGB 颜色
 * @param {Object} param0 - 包含 RGB 颜色值的对象
 * @param {number} param0.r - 红色通道值，范围 0 - 255
 * @param {number} param0.g - 绿色通道值，范围 0 - 255
 * @param {number} param0.b - 蓝色通道值，范围 0 - 255
 * @param {number} percent - 亮度调整的百分比，正数为调亮，负数为调暗
 * @returns {Array} - 包含调整后 RGB 颜色值的数组
 */
function adjust_lightness({ r, g, b }, percent) {
  // 归一化 RGB 值到 [0, 1] 范围
  const rNormalized = r / 255;
  const gNormalized = g / 255;
  const bNormalized = b / 255;

  // 转换为 HSL
  const max = Math.max(rNormalized, gNormalized, bNormalized);
  const min = Math.min(rNormalized, gNormalized, bNormalized);
  let h, s, l = (max + min) / 2;

  if (max === min) {
    h = s = 0; // 灰度
  } else {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case rNormalized:
        h = (gNormalized - bNormalized) / d + (gNormalized < bNormalized ? 6 : 0);
        break;
      case gNormalized:
        h = (bNormalized - rNormalized) / d + 2;
        break;
      case bNormalized:
        h = (rNormalized - gNormalized) / d + 4;
        break;
    }
    h /= 6;
  }

  // 调整亮度
  l = Math.min(1, Math.max(0, l + percent / 400));

  // 转换回 RGB
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  const p = 2 * l - q;
  const toRGB = (t) => {
    if (t < 0) t += 1;
    if (t > 1) t -= 1;
    if (t < 1 / 6) return p + (q - p) * 6 * t;
    if (t < 1 / 2) return q;
    if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
    return p;
  };

  const newR = Math.round(toRGB(h + 1 / 3) * 255);
  const newG = Math.round(toRGB(h) * 255);
  const newB = Math.round(toRGB(h - 1 / 3) * 255);

  return [newR, newG, newB];
}

/**
 * 调亮指定 RGB 颜色值
 * @param {Object} param0 - 包含 RGB 颜色值的对象
 * @param {number} param0.r - 红色通道值，范围 0 - 255
 * @param {number} param0.g - 绿色通道值，范围 0 - 255
 * @param {number} param0.b - 蓝色通道值，范围 0 - 255
 * @param {number} percent - 亮度增加的百分比，范围 0 - 100
 * @returns {Array} - 包含调整后 RGB 颜色值的数组
 */
function lighten_color({ r, g, b }, percent) {
  return adjust_lightness({ r, g, b }, percent);
}

/**
 * 调暗指定 RGB 颜色值
 * @param {Object} param0 - 包含 RGB 颜色值的对象
 * @param {number} param0.r - 红色通道值，范围 0 - 255
 * @param {number} param0.g - 绿色通道值，范围 0 - 255
 * @param {number} param0.b - 蓝色通道值，范围 0 - 255
 * @param {number} percent - 亮度减少的百分比，范围 0 - 100
 * @returns {Array} - 包含调整后 RGB 颜色值的数组
 */
function darken_color({ r, g, b }, percent) {
  return adjust_lightness({ r, g, b }, -percent);
}

/**
 * 将输入的颜色值字符串解析为包含 RGB 或 RGBA 通道值的数组
 * @param {string} v - 输入的颜色值字符串，支持 RGB、RGBA 和十六进制格式
 * @returns {number[]} - 包含 RGB 或 RGBA 通道值的数组，格式为 [r, g, b] 或 [r, g, b, a]
 */
const split_colors = (v) => {
  const color = v.trim();
  const rgbaRegex =
    /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0(\.\d+)?|1(\.0+)?)\s*\)$/i;
  const rgbRegex = /^rgb?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i;
  const hexRegex =
    /^#?([a-fA-F0-9]{3}|[a-fA-F0-9]{6}|[a-fA-F0-9]{4}|[a-fA-F0-9]{8})$/;
  let color_list;
  if (rgbaRegex.test(color)) {
    // 去掉 "rgba(" 和 ")"，然后按逗号分割
    const cleaned_str = color.slice(5, -1); // 去掉 "rgba(" 和最后的 ")"
    const parts = cleaned_str.split(",").map((str) => str.trim()); // 分割并去掉多余的空格
    color_list = parts.map(Number); // 将字符串转换为数字
    color_list[3] = Math.round(color_list[3] * 255);
  } else if (rgbRegex.test(color)) {
    // 去掉 "rgb(" 和 ")"，然后按逗号分割
    const cleaned_str = color.slice(4, -1); // 去掉 "rgba(" 和最后的 ")"
    const parts = cleaned_str.split(",").map((str) => str.trim()); // 分割并去掉多余的空格
    color_list = parts.map(Number); // 将字符串转换为数字
  } else if (hexRegex.test(color)) {
    let cleaned_str = color;
    if (color.includes("#")) {
      cleaned_str = color.slice(1);
    }
    // 检查是否是 6 位（RGB）或 8 位（RGBA）
    if (cleaned_str.length === 6 || cleaned_str.length === 8) {
      // 将字符串每两位分割一次
      const parts = [];
      for (let i = 0; i < cleaned_str.length; i += 2) {
        parts.push(cleaned_str.slice(i, i + 2));
      }
      // 将每对字符转换为数字（如果需要的话，可以转换为 10 进制整数）
      color_list = parts.map((part) => parseInt(part, 16));
    } else {
      const parts = [];
      for (let i = 0; i < cleaned_str.length; i++) {
        parts.push(cleaned_str.slice(i, i + 1));
      }
      color_list = parts.map((part) => parseInt(part + part, 16));
    }
  } else {
    color_list = [0, 0, 0, 255];
    msg.msg_error("请输入正确的颜色值!");
  }
  return color_list;
};

/**
 * 根据输入的颜色通道值数组，将其转换为对应的 RGB 或 RGBA 颜色字符串。
 * 若数组长度为 3，则转换为 RGB 格式字符串；若长度为 4，则转换为 RGBA 格式字符串。
 * 
 * @param {number[]} color_list - 包含 RGB 或 RGBA 通道值的数组。
 * 当长度为 3 时，格式为 [r, g, b]；当长度为 4 时，格式为 [r, g, b, a]。
 * 其中 r、g、b 范围是 0 - 255，a 范围是 0 - 255（后续会转换为 0 - 1 之间的小数）。
 * @returns {string} - 转换后的 RGB 或 RGBA 颜色字符串。
 */
const slider_input = (color_list) => {
  if (color_list.length === 3) {
    return `rgb(${color_list.join(", ")})`;
  } else if (color_list.length === 4) {
    let [r, g, b, a] = [...color_list];
    a = (a / 255).toFixed(2);
    return `rgba(${r}, ${g}, ${b}, ${a})`;
  }
};

export {
  draw_image_to_canvas,
  get_color,
  lighten_color,
  darken_color,
  split_colors,
  slider_input
};
